# src/files/knowledge.py
from flask import request, jsonify
from src.pojo.knowledge import Knowledge
from database.database import db
from datetime import datetime
import base64
import hashlib
import os


def register_knowledge_routes(app):
    # 添加知识条目
    @app.route('/knowledge', methods=['POST'])
    def add_knowledge():
        data = request.get_json()
        kno_id = data.get('kno_id')
        kno_title = data.get('kno_title')
        kno_type = data.get('kno_type')
        kno_url = data.get('kno_url')
        kno_authid = data.get('kno_authid')
        kno_style = data.get('kno_style')
        kno_createtime_str = data.get('kno_createtime')
        kno_updatetime_str = data.get('kno_updatetime')

        # 检查必填字段
        if not kno_id or not kno_title or not kno_type or not kno_authid or not kno_style or not kno_createtime_str or not kno_updatetime_str:
            return jsonify({'code': 401, 'message': '缺少必要参数'}), 401

        # 检查知识ID是否已存在
        existing_knowledge = Knowledge.query.filter_by(kno_id=kno_id).first()
        if existing_knowledge:
            return jsonify({'code': 402, 'message': '知识ID已存在'}), 402

        try:
            # 解析时间字符串为datetime对象
            # 支持多种时间格式
            try:
                if 'T' in kno_createtime_str:
                    # ISO格式: 2024-01-01T12:00:00
                    kno_createtime = datetime.fromisoformat(kno_createtime_str.replace('Z', ''))
                else:
                    # 数据库格式: 2024-01-01 12:00:00
                    kno_createtime = datetime.strptime(kno_createtime_str, '%Y-%m-%d %H:%M:%S')
            except ValueError:
                kno_createtime = datetime.now()

            try:
                if 'T' in kno_updatetime_str:
                    # ISO格式: 2024-01-01T12:00:00
                    kno_updatetime = datetime.fromisoformat(kno_updatetime_str.replace('Z', ''))
                else:
                    # 数据库格式: 2024-01-01 12:00:00
                    kno_updatetime = datetime.strptime(kno_updatetime_str, '%Y-%m-%d %H:%M:%S')
            except ValueError:
                kno_updatetime = datetime.now()

            # 检查kno_url大小，如果太大则保存为文件
            max_db_field_size = 65535  # TEXT字段最大大小
            if kno_url and len(kno_url) > max_db_field_size:
                # 创建文件存储目录
                file_storage_path = os.path.join(os.getcwd(), 'file_storage')
                if not os.path.exists(file_storage_path):
                    os.makedirs(file_storage_path)
                
                # 生成文件名
                file_extension = '.txt'  # Base64数据保存为txt文件
                filename = f"{kno_id}{file_extension}"
                file_path = os.path.join(file_storage_path, filename)
                
                # 保存Base64数据到文件
                try:
                    with open(file_path, 'w', encoding='utf-8') as f:
                        f.write(kno_url)
                    
                    # 将文件路径存储到数据库而不是原始数据
                    kno_url = f"/file_storage/{filename}"
                except Exception as file_error:
                    print(f"保存文件失败: {str(file_error)}")
                    # 如果保存文件失败，尝试截断数据
                    kno_url = kno_url[:max_db_field_size]

            # 创建新知识条目
            new_knowledge = Knowledge(
                kno_id=kno_id,
                kno_title=kno_title,
                kno_type=kno_type,
                kno_url=kno_url,
                kno_authid=kno_authid,
                kno_style=kno_style,
                kno_createtime=kno_createtime,
                kno_updatetime=kno_updatetime
            )

            # 尝试多次连接数据库以防网络波动
            max_retries = 3
            for attempt in range(max_retries):
                try:
                    db.session.add(new_knowledge)
                    db.session.commit()
                    return jsonify({'code': 200, 'message': '知识创建成功', 'data': new_knowledge.to_dict()}), 200
                except Exception as e:
                    db.session.rollback()
                    if attempt < max_retries - 1:
                        # 等待一段时间后重试
                        import time
                        time.sleep(1)
                        continue
                    else:
                        raise e

        except Exception as e:
            print(f"创建知识失败: {str(e)}")  # 添加详细错误日志
            return jsonify({'code': 500, 'message': '创建知识失败: ' + str(e)}), 500

    # 查询所有知识条目
    @app.route('/knowledges', methods=['GET'])
    def get_knowledges():
        try:
            knowledges = Knowledge.query.all()
            knowledges_list = [knowledge.to_dict() for knowledge in knowledges]
            return jsonify({'code': 200, 'message': '查询成功', 'data': knowledges_list}), 200
        except Exception as e:
            return jsonify({'code': 500, 'message': '查询失败: ' + str(e)}), 500

    # 根据ID查询知识条目
    @app.route('/knowledge/<kno_id>', methods=['GET'])
    def get_knowledge(kno_id):
        try:
            knowledge = Knowledge.query.filter_by(kno_id=kno_id).first()
            if knowledge:
                result_data = knowledge.to_dict()
                
                # 如果存储的是文件路径，则读取文件内容
                if result_data['kno_url'].startswith('/file_storage/'):
                    try:
                        file_path = os.path.join(os.getcwd(), 'file_storage', os.path.basename(result_data['kno_url']))
                        if os.path.exists(file_path):
                            with open(file_path, 'r', encoding='utf-8') as f:
                                result_data['kno_url'] = f.read()
                    except Exception as file_error:
                        print(f"读取文件失败: {str(file_error)}")
                
                return jsonify({'code': 200, 'message': '查询成功', 'data': result_data}), 200
            else:
                return jsonify({'code': 404, 'message': '知识不存在'}), 404
        except Exception as e:
            return jsonify({'code': 500, 'message': '查询失败: ' + str(e)}), 500

    # 更新知识条目
    @app.route('/knowledge/<kno_id>', methods=['PUT'])
    def update_knowledge(kno_id):
        data = request.get_json()
        kno_title = data.get('kno_title')
        kno_type = data.get('kno_type')
        kno_url = data.get('kno_url')
        kno_authid = data.get('kno_authid')
        kno_style = data.get('kno_style')
        kno_updatetime = data.get('kno_updatetime')

        # 检查必填字段
        if not kno_title or not kno_type or not kno_authid or not kno_style or not kno_updatetime:
            return jsonify({'code': 401, 'message': '缺少必要参数'}), 401

        # 查找知识条目
        knowledge = Knowledge.query.filter_by(kno_id=kno_id).first()
        if not knowledge:
            return jsonify({'code': 404, 'message': '知识不存在'}), 404

        # 更新字段
        knowledge.kno_title = kno_title
        knowledge.kno_type = kno_type
        knowledge.kno_authid = kno_authid
        knowledge.kno_style = kno_style
        knowledge.kno_updatetime = kno_updatetime

        # 处理kno_url更新
        if kno_url:
            max_db_field_size = 65535
            if len(kno_url) > max_db_field_size:
                # 创建文件存储目录
                file_storage_path = os.path.join(os.getcwd(), 'file_storage')
                if not os.path.exists(file_storage_path):
                    os.makedirs(file_storage_path)
                
                # 生成文件名
                file_extension = '.txt'
                filename = f"{kno_id}{file_extension}"
                file_path = os.path.join(file_storage_path, filename)
                
                # 保存Base64数据到文件
                try:
                    with open(file_path, 'w', encoding='utf-8') as f:
                        f.write(kno_url)
                    
                    # 将文件路径存储到数据库而不是原始数据
                    knowledge.kno_url = f"/file_storage/{filename}"
                except Exception as file_error:
                    print(f"更新文件失败: {str(file_error)}")
                    # 如果保存文件失败，尝试截断数据
                    knowledge.kno_url = kno_url[:max_db_field_size]
            else:
                knowledge.kno_url = kno_url

        try:
            # 尝试多次连接数据库以防网络波动
            max_retries = 3
            for attempt in range(max_retries):
                try:
                    db.session.commit()
                    return jsonify({'code': 200, 'message': '知识更新成功', 'data': knowledge.to_dict()}), 200
                except Exception as e:
                    db.session.rollback()
                    if attempt < max_retries - 1:
                        # 等待一段时间后重试
                        import time
                        time.sleep(1)
                        continue
                    else:
                        raise e
        except Exception as e:
            return jsonify({'code': 500, 'message': '更新知识失败: ' + str(e)}), 500

    # 删除知识条目
    @app.route('/knowledge/<kno_id>', methods=['DELETE'])
    def delete_knowledge(kno_id):
        try:
            knowledge = Knowledge.query.filter_by(kno_id=kno_id).first()
            if not knowledge:
                return jsonify({'code': 404, 'message': '知识不存在'}), 404

            # 如果存储的是文件，同时删除文件
            if knowledge.kno_url.startswith('/file_storage/'):
                try:
                    file_path = os.path.join(os.getcwd(), 'file_storage', os.path.basename(knowledge.kno_url))
                    if os.path.exists(file_path):
                        os.remove(file_path)
                except Exception as file_error:
                    print(f"删除文件失败: {str(file_error)}")

            # 尝试多次连接数据库以防网络波动
            max_retries = 3
            for attempt in range(max_retries):
                try:
                    db.session.delete(knowledge)
                    db.session.commit()
                    return jsonify({'code': 200, 'message': '知识删除成功'}), 200
                except Exception as e:
                    db.session.rollback()
                    if attempt < max_retries - 1:
                        # 等待一段时间后重试
                        import time
                        time.sleep(1)
                        continue
                    else:
                        raise e
        except Exception as e:
            return jsonify({'code': 500, 'message': '删除知识失败: ' + str(e)}), 500

    # 获取知识文档统计信息
    @app.route('/knowledge/stats', methods=['GET'])
    def get_knowledge_stats():
        try:
            # 按分类统计知识文档数量
            from sqlalchemy import func
            stats = db.session.query(
                Knowledge.kno_type,
                func.count(Knowledge.kno_id).label('count')
            ).group_by(Knowledge.kno_type).all()

            # 转换为字典格式
            stats_dict = {stat.kno_type: stat.count for stat in stats}

            return jsonify({'code': 200, 'message': '统计信息获取成功', 'data': stats_dict}), 200
        except Exception as e:
            return jsonify({'code': 500, 'message': '获取统计信息失败: ' + str(e)}), 500

    # 提供文件访问接口
    @app.route('/file_storage/<filename>', methods=['GET'])
    def get_file(filename):
        try:
            file_path = os.path.join(os.getcwd(), 'file_storage', filename)
            if os.path.exists(file_path):
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                return jsonify({'code': 200, 'data': content}), 200
            else:
                return jsonify({'code': 404, 'message': '文件不存在'}), 404
        except Exception as e:
            return jsonify({'code': 500, 'message': '读取文件失败: ' + str(e)}), 500